package com.minimalist.lindi.controller;

import cn.hutool.core.lang.Assert;
import cn.hutool.http.HttpStatus;
import com.minimalist.common.config.exception.BusinessException;
import com.minimalist.common.config.mybatis.bo.PageResp;
import com.minimalist.common.entity.basic.vo.file.FileUploadRespVO;
import com.minimalist.common.entity.lindi.vo.activity.LindiActivityQueryVO;
import com.minimalist.common.entity.lindi.vo.activity.LindiActivityVO;
import com.minimalist.common.entity.lindi.vo.enterpriseaccount.LindiEnterpriseAccountVO;
import com.minimalist.common.entity.lindi.vo.enterpriseregistration.LindiEnterpriseRegistrationVO;
import com.minimalist.common.entity.lindi.vo.laws.LindiLawsQueryVO;
import com.minimalist.common.entity.lindi.vo.laws.LindiLawsVO;
import com.minimalist.common.entity.lindi.vo.news.LindiNewsQueryVO;
import com.minimalist.common.entity.lindi.vo.news.LindiNewsVO;
import com.minimalist.common.entity.lindi.vo.subsidyapplication.LindiSubsidyApplicationVO;
import com.minimalist.common.entity.lindi.vo.tradeapplication.LindiTradeApplicationQueryVO;
import com.minimalist.common.entity.lindi.vo.tradeapplication.LindiTradeApplicationVO;
import com.minimalist.common.feign.client.basic.FileFeignClient;
import com.minimalist.common.response.R;
import com.minimalist.common.utils.JwtUtil;
import com.minimalist.lindi.manager.DashboardManager;
import com.minimalist.lindi.manager.LindiTradeApplicationManager;
import com.minimalist.lindi.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.NotBlank;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 林地指标平台对外API接口
 *
 * @author minimalist
 * @since 2024-11-01
 */
@RestController
@RequestMapping("/lindi/api")
@Validated
@Tag(name = "林地指标平台_对外API接口")
public class ApiController{

    private static final Logger log = LoggerFactory.getLogger(ApiController.class);

    private final LindiEnterpriseAccountService lindiEnterpriseAccountService;
    private final LindiTradeApplicationService lindiTradeApplicationService;
    private final LindiSubsidyApplicationService lindiSubsidyApplicationService;
    private final LindiNewsService lindiNewsService;
    private final LindiLawsService lindiLawsService;
    private final LindiActivityService lindiActivityService;
    private final LindiEnterpriseRegistrationService lindiEnterpriseRegistrationService;
    private final DashboardManager dashboardManager;
    private final LindiTradeApplicationManager lindiTradeApplicationManager;
    private final FileFeignClient fileFeignClient;

    public ApiController(LindiEnterpriseAccountService lindiEnterpriseAccountService,
                         LindiTradeApplicationService lindiTradeApplicationService,
                         LindiSubsidyApplicationService lindiSubsidyApplicationService,
                         LindiNewsService lindiNewsService,
                         LindiLawsService lindiLawsService,
                         LindiActivityService lindiActivityService,
                         LindiEnterpriseRegistrationService lindiEnterpriseRegistrationService,
                         DashboardManager dashboardManager,
                         LindiTradeApplicationManager lindiTradeApplicationManager,
                         FileFeignClient fileFeignClient){
        this.lindiEnterpriseAccountService = lindiEnterpriseAccountService;
        this.lindiTradeApplicationService = lindiTradeApplicationService;
        this.lindiSubsidyApplicationService = lindiSubsidyApplicationService;
        this.lindiNewsService = lindiNewsService;
        this.lindiLawsService = lindiLawsService;
        this.lindiActivityService = lindiActivityService;
        this.lindiEnterpriseRegistrationService = lindiEnterpriseRegistrationService;
        this.dashboardManager = dashboardManager;
        this.lindiTradeApplicationManager = lindiTradeApplicationManager;
        this.fileFeignClient = fileFeignClient;
    }

    /**
     * 企业用户登录
     *
     * @param mobile   企业联系方式（手机号）
     * @param password 企业密码
     * @return 登录结果
     */
    @PostMapping("/enterprise/login")
    @Operation(summary = "企业用户登录", description = "企业用户通过手机号和密码登录")
    public R<Map<String, Object>> enterpriseLogin(
            @Parameter(description = "企业联系方式（手机号）", required = true)
            @RequestParam("mobile") @NotBlank(message = "手机号不能为空") String mobile,
            @Parameter(description = "企业密码", required = true)
            @RequestParam("password") @NotBlank(message = "密码不能为空") String password){

        try{
            // 验证企业用户登录
            LindiEnterpriseAccountVO enterpriseAccount =
                    lindiEnterpriseAccountService.loginByMobile(mobile, password);

            if (enterpriseAccount == null){
                return R.fail("手机号或密码错误");
            }

            // 检查账户状态
            if (enterpriseAccount.getStatus() == null || enterpriseAccount.getStatus() != 1){
                return R.fail("账户已被禁用，请联系管理员");
            }

            // 生成JWT Token
            String token = JwtUtil.generateToken(
                    enterpriseAccount.getEnterpriseAccountId(),
                    enterpriseAccount.getEnterpriseMobile()
            );

            Map<String, Object> result = new HashMap<>(16);
            result.put("token", token);
            result.put("enterpriseAccount", enterpriseAccount);

            log.info("企业用户登录成功: {}", mobile);
            return R.ok(result);

        } catch (Exception e){
            log.error("企业用户登录失败: {}", mobile, e);
            return R.fail("登录失败，请稍后重试");
        }
    }

    /**
     * 查询企业用户信息
     *
     * @param request HTTP请求对象
     * @return 企业用户信息
     */
    @GetMapping("/enterprise/info")
    @Operation(summary = "查询企业用户信息", description = "根据JWT Token查询企业用户信息")
    public R<LindiEnterpriseAccountVO> getEnterpriseInfo(HttpServletRequest request){

        try{
            // 验证Token
            String token = request.getHeader("Authorization");
            if (token == null || token.isEmpty()){
                return R.fail(401, "未提供认证令牌");
            }

            // 从Token中获取企业用户ID
            Long enterpriseAccountId = JwtUtil.getUserId(token);
            if (enterpriseAccountId == null){
                return R.fail(401, "Token中缺少用户信息");
            }

            // 查询企业用户信息
            LindiEnterpriseAccountVO enterpriseAccount =
                    lindiEnterpriseAccountService.getEnterpriseAccountByEnterpriseAccountId(enterpriseAccountId);

            if (enterpriseAccount == null){
                return R.fail("企业用户不存在");
            }

            // 检查账户状态
            if (enterpriseAccount.getStatus() == null || enterpriseAccount.getStatus() != 1){
                return R.fail("账户已被禁用");
            }

            // 清除敏感信息
            enterpriseAccount.setEnterprisePassword(null);

            return R.ok(enterpriseAccount);

        } catch (Exception e){
            log.error("查询企业用户信息失败", e);
            return R.fail("查询失败，请稍后重试");
        }
    }

    /**
     * 根据企业用户ID查询企业用户信息
     *
     * @param enterpriseAccountId 企业用户ID
     * @return 企业用户信息
     */
    @GetMapping("/enterprise/info/{enterpriseAccountId}")
    @Operation(summary = "根据ID查询企业用户信息", description = "根据企业用户ID查询企业用户信息")
    public R<LindiEnterpriseAccountVO> getEnterpriseInfoById(
            @Parameter(description = "企业用户ID", required = true)
            @PathVariable Long enterpriseAccountId){

        try{
            if (enterpriseAccountId == null){
                return R.fail("企业用户ID不能为空");
            }

            // 查询企业用户信息
            LindiEnterpriseAccountVO enterpriseAccount =
                    lindiEnterpriseAccountService
                            .getEnterpriseAccountByEnterpriseAccountId(enterpriseAccountId);

            if (enterpriseAccount == null){
                return R.fail("企业用户不存在");
            }

            // 清除敏感信息
            enterpriseAccount.setEnterprisePassword(null);

            return R.ok(enterpriseAccount);

        } catch (Exception e){
            log.error("根据ID查询企业用户信息失败: {}", enterpriseAccountId, e);
            return R.fail("查询失败，请稍后重试");
        }
    }

    /**
     * 分页查询已完成的交易记录
     *
     * @param queryVO 查询条件
     * @return 已完成的交易记录分页数据
     */
    @PostMapping("/trade/completed")
    @Operation(summary = "分页查询已完成的交易记录",
            description = "查询交易状态为'林业局审批通过-交易完成'的交易记录，返回交易编号、项目名称、坐落镇街、面积、价格、交易日期等信息")
    public R<PageResp<LindiTradeApplicationVO>> getCompletedTradeApplications(
            @Parameter(description = "查询条件", required = true)
            @RequestBody LindiTradeApplicationQueryVO queryVO){

        try{
            log.info("分页查询已完成的交易记录，查询参数：{}", queryVO);

            // 调用服务层方法查询已完成的交易记录
            PageResp<LindiTradeApplicationVO> pageResp =
                    lindiTradeApplicationService.getCompletedTradeApplicationList(queryVO);

            log.info("分页查询已完成的交易记录成功，共查询到{}条记录", pageResp.getTotal());
            return R.ok(pageResp);

        } catch (Exception e){
            log.error("分页查询已完成的交易记录失败", e);
            return R.fail("查询已完成的交易记录失败，请稍后重试");
        }
    }

    /**
     * 获取网站新闻封面轮播图列表
     *
     * @return 新闻轮播图列表
     */
    @GetMapping("/news/carousel")
    @Operation(summary = "获取网站新闻封面轮播图列表",
            description = "获取置顶且有封面图的新闻列表，用于首页轮播图展示，最多返回5条")
    public R<PageResp<LindiNewsVO>> getNewsCarousel(){

        try{
            log.info("获取网站新闻封面轮播图列表");

            // 调用服务层方法获取轮播图新闻列表
            PageResp<LindiNewsVO> pageResp = lindiNewsService.getCarouselNewsList();

            log.info("获取网站新闻封面轮播图列表成功，共查询到{}条记录", pageResp.getTotal());
            return R.ok(pageResp);

        } catch (Exception e){
            log.error("获取网站新闻封面轮播图列表失败", e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 获取网站新闻列表
     *
     * @param queryVO 查询条件
     * @return 新闻列表
     */
    @PostMapping("/news/list")
    @Operation(summary = "获取网站新闻列表",
            description = "分页查询网站新闻列表，支持按标题搜索，只返回状态正常的新闻")
    public R<PageResp<LindiNewsVO>> getNewsList(
            @Parameter(description = "查询条件", required = true)
            @RequestBody LindiNewsQueryVO queryVO){

        try{
            log.info("获取网站新闻列表，查询参数：{}", queryVO);

            // 调用服务层方法获取新闻列表
            PageResp<LindiNewsVO> pageResp = lindiNewsService.getPageNewsList(queryVO);

            log.info("获取网站新闻列表成功，共查询到{}条记录", pageResp.getTotal());
            return R.ok(pageResp);

        } catch (Exception e){
            log.error("获取网站新闻列表失败", e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 获取新闻详情
     *
     * @param newsId 新闻ID
     * @return 新闻详情
     */
    @GetMapping("/news/{newsId}")
    @Operation(summary = "获取新闻详情",
            description = "根据新闻ID获取新闻详情，包含完整的新闻内容和封面图片")
    public R<LindiNewsVO> getNewsDetail(
            @Parameter(description = "新闻ID", required = true)
            @PathVariable Long newsId){

        try{
            log.info("获取新闻详情，新闻ID：{}", newsId);

            // 调用服务层方法获取新闻详情
            LindiNewsVO newsVO = lindiNewsService.getNewsByNewsId(newsId);

            log.info("获取新闻详情成功，新闻标题：{}", newsVO.getNewsTitle());
            return R.ok(newsVO);

        } catch (Exception e){
            log.error("获取新闻详情失败，新闻ID：{}", newsId, e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 获取网站政策法规列表
     *
     * @param queryVO 查询条件
     * @return 政策法规列表
     */
    @PostMapping("/laws/list")
    @Operation(summary = "获取网站政策法规列表",
            description = "分页查询网站政策法规列表，支持按标题搜索，只返回状态正常的政策法规")
    public R<PageResp<LindiLawsVO>> getLawsList(
            @Parameter(description = "查询条件", required = true)
            @RequestBody LindiLawsQueryVO queryVO){

        try{
            log.info("获取网站政策法规列表，查询条件：{}", queryVO);

            // 调用服务层方法获取政策法规列表
            PageResp<LindiLawsVO> pageResp = lindiLawsService.getPageLawsList(queryVO);

            log.info("获取网站政策法规列表成功，共查询到{}条记录", pageResp.getTotal());
            return R.ok(pageResp);

        } catch (Exception e){
            log.error("获取网站政策法规列表失败", e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 获取政策法规详情
     *
     * @param lawsId 政策法规ID
     * @return 政策法规详情
     */
    @GetMapping("/laws/{lawsId}")
    @Operation(summary = "获取政策法规详情",
            description = "根据政策法规ID获取详情信息，只返回状态正常的政策法规")
    public R<LindiLawsVO> getLawsDetail(
            @Parameter(description = "政策法规ID", required = true)
            @PathVariable Long lawsId){

        try{
            log.info("获取政策法规详情，政策法规ID：{}", lawsId);

            // 调用服务层方法获取政策法规详情
            LindiLawsVO lawsVO = lindiLawsService.getLawsByLawsId(lawsId);

            log.info("获取政策法规详情成功，政策法规标题：{}", lawsVO.getLawsTitle());
            return R.ok(lawsVO);

        } catch (Exception e){
            log.error("获取政策法规详情失败，政策法规ID：{}", lawsId, e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 获取最新四个法规
     *
     * @return 最新四个法规列表（包含标题和内容前200个字符）
     */
    @GetMapping("/laws/latest")
    @Operation(summary = "获取最新四个法规",
            description = "获取最新发布的四个法规，包含标题和内容前200个字符")
    public R<List<LindiLawsVO>> getLatestLaws(){

        try{
            log.info("获取最新四个法规");

            // 构建查询条件：状态为1（已发布），分页大小为4
            LindiLawsQueryVO queryVO = new LindiLawsQueryVO();
            queryVO.setStatus(1);
            queryVO.setPageNum(1L);
            queryVO.setPageSize(4L);

            // 调用服务层方法获取法规列表
            PageResp<LindiLawsVO> pageResp = lindiLawsService.getPageLawsList(queryVO);

            // 截取内容前200个字符
            List<LindiLawsVO> lawsList = pageResp.getRecords();
            lawsList.forEach(laws -> {
                if (laws.getLawsContent() != null && laws.getLawsContent().length() > 200){
                    laws.setLawsContent(laws.getLawsContent().substring(0, 200) + "...");
                }
            });

            log.info("获取最新四个法规成功，共查询到{}条记录", pageResp.getRecords().size());
            return R.ok(lawsList);
        } catch (Exception e){
            log.error("获取最新四个法规失败", e);
            return R.fail("获取最新四个法规失败");
        }
    }

    /**
     * 获取网站活动列表
     *
     * @param queryVO 查询条件
     * @return 活动列表
     */
    @PostMapping("/activities")
    @Operation(summary = "获取网站活动列表",
            description = "分页查询网站活动列表，支持按标题搜索，只返回状态正常的活动")
    public R<PageResp<LindiActivityVO>> getActivityList(
            @Parameter(description = "查询条件", required = true)
            @RequestBody LindiActivityQueryVO queryVO){

        try{
            log.info("获取网站活动列表，查询条件：{}", queryVO);

            // 调用服务层方法获取活动列表
            PageResp<LindiActivityVO> pageResp = lindiActivityService.getPageActivityList(queryVO);

            log.info("获取网站活动列表成功，共查询到{}条记录", pageResp.getTotal());
            return R.ok(pageResp);

        } catch (Exception e){
            log.error("获取网站活动列表失败", e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 获取活动详情
     *
     * @param activityId 活动ID
     * @return 活动详情
     */
    @GetMapping("/activity/{activityId}")
    @Operation(summary = "获取活动详情",
            description = "根据活动ID获取详情信息，只返回状态正常的活动")
    public R<LindiActivityVO> getActivityDetail(
            @Parameter(description = "活动ID", required = true)
            @PathVariable Long activityId){

        try{
            log.info("获取活动详情，活动ID：{}", activityId);

            // 调用服务层方法获取活动详情
            LindiActivityVO activityVO = lindiActivityService.getActivityByActivityId(activityId);

            log.info("获取活动详情成功，活动标题：{}", activityVO.getActivityTitle());
            return R.ok(activityVO);

        } catch (Exception e){
            log.error("获取活动详情失败，活动ID：{}", activityId, e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 获取平台统计概览数据
     *
     * @return 平台统计概览数据，包括累计交易额、累计成交订单量、累计注册企业和总林地面积
     */
    @GetMapping("/dashboard/overview")
    @Operation(summary = "获取平台统计概览数据",
            description = "获取平台累计交易额、累计成交订单量、累计注册企业和总林地面积等统计数据")
    public R<Map<String, Object>> getDashboardOverview(){

        try{
            log.info("获取平台统计概览数据");

            // 调用DashboardManager获取平台概览数据
            Map<String, Object> overviewData = dashboardManager.getPlatformOverview();

            log.info("获取平台统计概览数据成功");
            return R.ok(overviewData);

        } catch (Exception e){
            log.error("获取平台统计概览数据失败", e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 获取各镇街林地面积统计数据
     *
     * @return 各镇街林地面积统计数据
     */
    @GetMapping("/dashboard/area-stats")
    @Operation(summary = "获取各镇街林地面积统计数据",
            description = "获取各街道镇区的林地面积统计数据，按镇街名称分组统计")
    public R<List<Map<String, Object>>> getAreaStatistics(){

        try{
            log.info("获取各镇街林地面积统计数据");

            // 调用DashboardManager获取面积统计数据
            List<Map<String, Object>> areaStats = dashboardManager.getAreaStatistics();

            log.info("获取各镇街林地面积统计数据成功");
            return R.ok(areaStats);

        } catch (Exception e){
            log.error("获取各镇街林地面积统计数据失败", e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 修改企业联系人信息
     *
     * @param request             HTTP请求对象
     * @param enterpriseAccountVO 企业账户信息（不包含ID）
     * @return 修改结果
     */
    @PostMapping("/enterprise/contact")
    @Operation(summary = "修改企业联系人信息",
            description = "企业用户修改联系人姓名和联系方式，通过JWT Token获取企业用户ID")
    public R<Void> updateEnterpriseContact(
            HttpServletRequest request,
            @Parameter(description = "企业账户信息（不包含ID）", required = true)
            @RequestBody LindiEnterpriseAccountVO enterpriseAccountVO){

        try{
            // 验证Token
            String token = request.getHeader("Authorization");
            if (token == null || token.isEmpty()){
                return R.fail(401, "未提供认证令牌");
            }

            // 从Token中获取企业用户ID
            Long enterpriseAccountId = JwtUtil.getUserId(token);
            if (enterpriseAccountId == null){
                return R.fail(401, "Token中缺少用户信息");
            }

            // 检查是否有需要更新的字段，如果传递的为空则不修改
            boolean hasUpdateFields = false;
            LindiEnterpriseAccountVO updateVO = new LindiEnterpriseAccountVO();
            updateVO.setEnterpriseAccountId(enterpriseAccountId);

            if (enterpriseAccountVO.getEnterprisePerson() != null && !enterpriseAccountVO.getEnterprisePerson().trim().isEmpty()){
                updateVO.setEnterprisePerson(enterpriseAccountVO.getEnterprisePerson());
                hasUpdateFields = true;
            }

            if (enterpriseAccountVO.getEnterpriseMobile() != null && !enterpriseAccountVO.getEnterpriseMobile().trim().isEmpty()){
                updateVO.setEnterpriseMobile(enterpriseAccountVO.getEnterpriseMobile());
                hasUpdateFields = true;
            }

            if (!hasUpdateFields){
                return R.fail("没有需要更新的联系人信息");
            }

            log.info("企业用户修改联系人信息，企业ID: {}", enterpriseAccountId);

            // 调用企业账户服务更新联系人信息
            lindiEnterpriseAccountService.updateEnterpriseAccountByEnterpriseAccountId(updateVO);

            log.info("企业联系人信息修改成功，企业ID: {}", enterpriseAccountId);
            return R.ok();

        } catch (Exception e){
            log.error("企业联系人信息修改失败", e);
            return R.fail("修改失败，" + e.getMessage());
        }
    }

    /**
     * 修改企业密码
     *
     * @param request             HTTP请求对象
     * @param enterpriseAccountVO 企业账户信息（包含新密码，不包含ID）
     * @return 修改结果
     */
    @PostMapping("/enterprise/password")
    @Operation(summary = "修改企业密码",
            description = "企业用户修改登录密码，通过JWT Token获取企业用户ID")
    public R<String> updateEnterprisePassword(
            HttpServletRequest request,
            @Parameter(description = "企业账户信息（包含新密码，不包含ID）", required = true)
            @RequestBody LindiEnterpriseAccountVO enterpriseAccountVO){

        try{
            // 验证Token
            String token = request.getHeader("Authorization");
            if (token == null || token.isEmpty()){
                return R.fail(401, "未提供认证令牌");
            }

            // 从Token中获取企业用户ID
            Long enterpriseAccountId = JwtUtil.getUserId(token);
            if (enterpriseAccountId == null){
                return R.fail(401, "Token中缺少用户信息");
            }

            // 检查密码是否为空，如果传递的为空则不修改
            if (enterpriseAccountVO.getEnterprisePassword() == null || enterpriseAccountVO.getEnterprisePassword().trim().isEmpty()){
                return R.fail("密码不能为空");
            }

            // 设置企业用户ID
            enterpriseAccountVO.setEnterpriseAccountId(enterpriseAccountId);

            log.info("企业用户修改密码，企业ID: {}", enterpriseAccountId);

            // 调用企业账户服务更新密码
            lindiEnterpriseAccountService.updateEnterpriseAccountByEnterpriseAccountId(
                    enterpriseAccountVO);

            log.info("企业密码修改成功，企业ID: {}", enterpriseAccountId);
            return R.ok("密码修改成功");

        } catch (Exception e){
            log.error("企业密码修改失败", e);
            return R.fail("修改失败，" + e.getMessage());
        }
    }

    /**
     * 获取交易申请详情
     *
     * @param tradeApplicationId 交易申请ID
     * @return 交易申请详情
     */
    @GetMapping("/trade-application/{tradeApplicationId}")
    @Operation(summary = "获取交易申请详情",
            description = "根据交易申请ID获取交易申请的详细信息")
    public R<LindiTradeApplicationVO> getTradeApplicationDetail(
            @Parameter(description = "交易申请ID", required = true)
            @PathVariable Long tradeApplicationId){

        try{
            log.info("获取交易申请详情，申请ID: {}", tradeApplicationId);

            // 调用交易申请服务获取详情
            LindiTradeApplicationVO tradeApplicationVO =
                    lindiTradeApplicationService
                            .getTradeApplicationByTradeApplicationId(tradeApplicationId);
            log.info("获取交易申请详情成功，申请详情: {}", tradeApplicationVO);

            if (tradeApplicationVO == null){
                log.warn("交易申请不存在，申请ID: {}", tradeApplicationId);
                return R.fail("交易申请不存在");
            }

            log.info("获取交易申请详情成功，申请ID: {}", tradeApplicationId);
            return R.ok(tradeApplicationVO);

        } catch (Exception e){
            log.error("获取交易申请详情失败，申请ID: {}", tradeApplicationId, e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 获取补贴申请详情
     *
     * @param subsidyApplicationId 补贴申请ID
     * @return 补贴申请详情
     */
    @GetMapping("/subsidy-application/{subsidyApplicationId}")
    @Operation(summary = "获取补贴申请详情",
            description = "根据补贴申请ID获取补贴申请的详细信息")
    public R<LindiSubsidyApplicationVO> getSubsidyApplicationDetail(
            @Parameter(description = "补贴申请ID", required = true)
            @PathVariable Long subsidyApplicationId){

        try{
            log.info("获取补贴申请详情，申请ID: {}", subsidyApplicationId);

            // 调用补贴申请服务获取详情
            LindiSubsidyApplicationVO subsidyApplicationVO =
                    lindiSubsidyApplicationService.getSubsidyApplicationBySubsidyApplicationId(subsidyApplicationId);

            if (subsidyApplicationVO == null){
                log.warn("补贴申请不存在，申请ID: {}", subsidyApplicationId);
                return R.fail("补贴申请不存在");
            }

            log.info("获取补贴申请详情成功，申请ID: {}", subsidyApplicationId);
            return R.ok(subsidyApplicationVO);

        } catch (Exception e){
            log.error("获取补贴申请详情失败，申请ID: {}", subsidyApplicationId, e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 根据企业用户token查询该企业用户的交易申请分页列表
     *
     * @param queryVO 查询条件
     * @param request HTTP请求对象，用于获取token
     * @return 交易申请分页列表
     */
    @PostMapping("/enterprise/trade-applications")
    @Operation(summary = "查询企业用户交易申请列表",
            description = "根据企业用户token查询该企业用户的交易申请分页列表")
    public R<PageResp<LindiTradeApplicationVO>> getEnterpriseTradeApplications(
            @Parameter(description = "查询条件", required = true)
            @RequestBody LindiTradeApplicationQueryVO queryVO,
            HttpServletRequest request){

        try{
            log.info("查询企业用户交易申请列表，查询参数：{}", queryVO);

            // 从token中获取企业用户ID
            String token = request.getHeader("Authorization");
            if (token == null || token.isEmpty()){
                return R.fail(401, "未提供认证令牌");
            }

            // 调用manager层方法查询企业用户的交易申请列表
            PageResp<LindiTradeApplicationVO> pageResp =
                    lindiTradeApplicationManager.getEnterpriseTradeApplicationList(token, queryVO);

            log.info("查询企业用户交易申请列表成功，共查询到{}条记录", pageResp.getTotal());
            return R.ok(pageResp);

        } catch (Exception e){
            log.error("查询企业用户交易申请列表失败", e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 根据企业用户token和交易申请ID查询交易申请详情
     *
     * @param tradeApplicationId 交易申请ID
     * @param request            HTTP请求对象，用于获取token
     * @return 交易申请详情
     */
    @GetMapping("/enterprise/trade-application/{tradeApplicationId}")
    @Operation(summary = "查询企业用户交易申请详情",
            description = "根据企业用户token和交易申请ID查询该企业用户的交易申请详情信息")
    public R<LindiTradeApplicationVO> getEnterpriseTradeApplicationDetail(
            @Parameter(description = "交易申请ID", required = true)
            @PathVariable Long tradeApplicationId,
            HttpServletRequest request){

        try{
            log.info("查询企业用户交易申请详情，申请ID: {}", tradeApplicationId);

            // 验证Token
            String token = request.getHeader("Authorization");
            if (token == null || token.isEmpty()){
                return R.fail(401, "未提供认证令牌");
            }

            // 从Token中获取企业用户ID
            Long enterpriseAccountId = JwtUtil.getUserId(token);
            if (enterpriseAccountId == null){
                return R.fail(401, "Token中缺少用户信息");
            }

            // 验证企业用户是否存在且状态正常
            LindiEnterpriseAccountVO enterpriseAccount =
                    lindiEnterpriseAccountService
                            .getEnterpriseAccountByEnterpriseAccountId(enterpriseAccountId);
            if (enterpriseAccount == null){
                return R.fail(401, "企业用户不存在");
            }
            if (enterpriseAccount.getStatus() == null || enterpriseAccount.getStatus() != 1){
                return R.fail(401, "账户已被禁用");
            }

            LindiTradeApplicationVO tradeApplicationVO =
                    lindiTradeApplicationService
                            .getTradeApplicationByTradeApplicationId(tradeApplicationId);

            if (tradeApplicationVO == null){
                log.warn("交易申请不存在，申请ID: {}", tradeApplicationId);
                return R.fail("交易申请不存在");
            }

            // 验证交易申请是否属于当前企业用户
            if (!enterpriseAccountId.equals(tradeApplicationVO.getEnterpriseAccountId())){
                log.warn("无权限访问该交易申请，企业用户ID: {}, 申请ID: {}", enterpriseAccountId, tradeApplicationId);
                return R.fail("无权限访问该交易申请");
            }

            log.info("查询企业用户交易申请详情成功，申请ID: {}", tradeApplicationId);
            return R.ok(tradeApplicationVO);

        } catch (Exception e){
            log.error("查询企业用户交易申请详情失败，申请ID: {}", tradeApplicationId, e);
            return R.fail("查询失败，" + e.getMessage());
        }
    }

    /**
     * 前台网页文件上传
     *
     * @param file       上传的文件
     * @param fileSource 文件来源（1-前台网页，2-企业注册，3-交易申请，4-补贴申请等）
     * @param request    HTTP请求对象
     * @return 文件上传结果
     */
    @PostMapping("/file/upload")
    @Operation(summary = "前台网页文件上传",
            description = "前台网页文件上传接口，支持各种文件类型上传，需要指定文件来源")
    public R<FileUploadRespVO> uploadFile(
            @Parameter(description = "上传的文件", required = true)
            @RequestParam("file") MultipartFile file,
            @Parameter(description = "文件来源（1-前台网页，2-企业注册，3-交易申请，4-补贴申请等）", required = true)
            @RequestParam("fileSource") Integer fileSource,
            HttpServletRequest request){

        try{
            log.info("前台网页文件上传，文件名：{}，文件来源：{}", file.getOriginalFilename(), fileSource);

            // 验证文件来源参数
            if (fileSource == null || fileSource < 1){
                return R.fail("文件来源参数无效");
            }

            // 从Token中获取用户信息（如果有的话）
            Long userId = null;
            String token = request.getHeader("Authorization");
            if (token != null && !token.isEmpty()){
                try{
                    userId = JwtUtil.getUserId(token);
                } catch (Exception ignored){
                    // Token解析失败，继续使用null
                }
            }

            // 调用文件服务上传文件
            R<FileUploadRespVO> result = fileFeignClient.uploadFile(
                    file,
                    fileSource,
                    0L,
                    0L,
                    0L
            );

            Assert.isTrue(result.getCode() == HttpStatus.HTTP_OK
                    , () -> new BusinessException("文件上传失败"));

            return R.ok(result.getData());

        } catch (Exception e){
            log.error("前台网页文件上传异常，文件名：{}", file.getOriginalFilename(), e);
            return R.fail("文件上传失败，" + e.getMessage());
        }
    }

    /**
     * 前台网页文件删除
     *
     * @param fileId 文件ID
     * @return 删除结果
     */
    @DeleteMapping("/file/delete")
    @Operation(summary = "前台网页文件删除",
            description = "根据文件ID删除文件")
    public R<Void> deleteFile(
            @Parameter(description = "文件ID", required = true)
            @RequestParam @NotBlank(message = "文件ID不能为空") String fileId){

        try{
            log.info("前台网页文件删除，文件ID：{}", fileId);

            // 调用文件服务删除文件
            R<Void> result = fileFeignClient.deleteFile(Long.valueOf(fileId));

            Assert.isTrue(result.getCode() == 200
                    , () -> new BusinessException("删除文件失败"));
            return R.ok();

        } catch (Exception e){
            log.error("前台网页文件删除异常，文件ID：{}", fileId, e);
            return R.fail("文件删除失败，" + e.getMessage());
        }
    }

    /**
     * 企业注册信息提交
     *
     * @param enterpriseRegistrationVO 企业注册信息
     * @return 提交结果
     */
    @PostMapping("/enterprise/register")
    @Operation(summary = "企业注册信息提交",
            description = "前台网页企业注册信息提交接口，提交企业基本信息和相关证件文件")
    public R<String> submitEnterpriseRegistration(
            @Parameter(description = "企业注册信息", required = true)
            @RequestBody LindiEnterpriseRegistrationVO enterpriseRegistrationVO){

        try{
            log.info("企业注册信息提交，企业名称：{}", enterpriseRegistrationVO.getEnterpriseName());

            // 调用企业注册服务提交注册信息
            lindiEnterpriseRegistrationService.addEnterpriseRegistration(enterpriseRegistrationVO);

            log.info("企业注册信息提交成功，企业名称：{}", enterpriseRegistrationVO.getEnterpriseName());
            return R.ok("企业注册信息提交成功，请等待审核");

        } catch (Exception e){
            log.error("企业注册信息提交失败，企业名称：{}", enterpriseRegistrationVO.getEnterpriseName(), e);
            return R.fail("企业注册信息提交失败，" + e.getMessage());
        }
    }

    /**
     * 企业提交交易申请
     *
     * @param request            HTTP请求对象
     * @param tradeApplicationVO 交易申请信息
     * @return 提交结果
     */
    @PostMapping("/enterprise/trade-application")
    @Operation(summary = "企业提交交易申请",
            description = "前台网页企业提交交易申请接口，需要JWT Token验证身份")
    public R<String> submitTradeApplication(
            HttpServletRequest request,
            @Parameter(description = "交易申请信息", required = true)
            @RequestBody LindiTradeApplicationVO tradeApplicationVO){

        try{
            // 验证Token
            String token = request.getHeader("Authorization");
            if (token == null || token.isEmpty()){
                return R.fail(401, "未提供认证令牌");
            }

            // 从Token中获取企业用户ID
            Long enterpriseAccountId = JwtUtil.getUserId(token);
            if (enterpriseAccountId == null){
                return R.fail(401, "Token中缺少用户信息");
            }

            // 设置申请人ID
            tradeApplicationVO.setEnterpriseAccountId(enterpriseAccountId);

            log.info("企业提交交易申请，企业用户ID：{}，项目名称：{}",
                    enterpriseAccountId, tradeApplicationVO.getProjectName());

            // 调用交易申请服务提交申请
            lindiTradeApplicationService.addTradeApplication(tradeApplicationVO);

            log.info("企业交易申请提交成功，企业用户ID：{}，项目名称：{}",
                    enterpriseAccountId, tradeApplicationVO.getProjectName());
            return R.ok("交易申请提交成功，请等待审核");

        } catch (Exception e){
            log.error("企业交易申请提交失败，项目名称：{}",
                    tradeApplicationVO.getProjectName(), e);
            return R.fail("交易申请提交失败，" + e.getMessage());
        }
    }

    /**
     * 企业提交补贴申请
     *
     * @param request              HTTP请求对象
     * @param subsidyApplicationVO 补贴申请信息
     * @return 提交结果
     */
    @PostMapping("/enterprise/subsidy-application")
    @Operation(summary = "企业提交补贴申请",
            description = "前台网页企业提交补贴申请接口，需要JWT Token验证身份")
    public R<String> submitSubsidyApplication(
            HttpServletRequest request,
            @Parameter(description = "补贴申请信息", required = true)
            @RequestBody LindiSubsidyApplicationVO subsidyApplicationVO){

        try{
            // 验证Token
            String token = request.getHeader("Authorization");
            if (token == null || token.isEmpty()){
                return R.fail(401, "未提供认证令牌");
            }

            // 从Token中获取企业用户ID
            Long enterpriseAccountId = JwtUtil.getUserId(token);
            if (enterpriseAccountId == null){
                return R.fail(401, "Token中缺少用户信息");
            }

            // 设置申请人ID
            subsidyApplicationVO.setEnterpriseAccountId(enterpriseAccountId);

            log.info("企业提交补贴申请，企业用户ID：{}，申请标题：{}",
                    enterpriseAccountId, subsidyApplicationVO.getProjectName());

            // 调用补贴申请服务提交申请
            lindiSubsidyApplicationService.addSubsidyApplication(subsidyApplicationVO);

            log.info("企业补贴申请提交成功，企业用户ID：{}，申请标题：{}",
                    enterpriseAccountId, subsidyApplicationVO.getProjectName());
            return R.ok("补贴申请提交成功，请等待审核");

        } catch (Exception e){
            log.error("企业补贴申请提交失败，申请标题：{}",
                    subsidyApplicationVO.getProjectName(), e);
            return R.fail("补贴申请提交失败，" + e.getMessage());
        }
    }
}

